Из открытых источников доступны исторические данные о продажах игр, оценки пользователей и экспертов, жанры и платформы. Необходимо выявить определяющие успешность игры закономерности. Это позволит сделать ставку на потенциально популярный продукт и спланировать рекламные кампании. Представим, что сейчас декабрь 2016 года, нужно спланировать рекламную кампанию на 2017 год.
import pandas as pd
import plotly.express as px
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats as st
import warnings
warnings.filterwarnings('ignore')
try:
games = pd.read_csv('/datasets/games.csv')
except:
games = pd.read_csv('games.csv')
games.head()
| Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
| 1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
| 2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
| 3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
games.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 16715 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Name 16713 non-null object 1 Platform 16715 non-null object 2 Year_of_Release 16446 non-null float64 3 Genre 16713 non-null object 4 NA_sales 16715 non-null float64 5 EU_sales 16715 non-null float64 6 JP_sales 16715 non-null float64 7 Other_sales 16715 non-null float64 8 Critic_Score 8137 non-null float64 9 User_Score 10014 non-null object 10 Rating 9949 non-null object dtypes: float64(6), object(5) memory usage: 1.4+ MB
Описание колонок:
Name — название игрыPlatform — платформаYear_of_Release — год выпускаGenre — жанр игрыNA_sales — продажи в Северной Америке (миллионы проданных копий)EU_sales — продажи в Европе (миллионы проданных копий)JP_sales — продажи в Японии (миллионы проданных копий)Other_sales — продажи в других странах (миллионы проданных копий)Critic_Score — оценка критиков (максимум 100)User_Score — оценка пользователей (максимум 10)Rating — рейтинг от организации ESRB (англ. Entertainment Software Rating Board). Эта ассоциация определяет рейтинг компьютерных игр и присваивает им подходящую возрастную категорию.Посмотрим количество явных дубликатов
games.duplicated().sum()
0
Явные дубликаты отсутствуют
Неявные дубликаты обработаем в разделе "Предобработка данных".
games.hist(figsize=(8, 8))
array([[<AxesSubplot:title={'center':'Year_of_Release'}>,
<AxesSubplot:title={'center':'NA_sales'}>],
[<AxesSubplot:title={'center':'EU_sales'}>,
<AxesSubplot:title={'center':'JP_sales'}>],
[<AxesSubplot:title={'center':'Other_sales'}>,
<AxesSubplot:title={'center':'Critic_Score'}>]], dtype=object)
По гистограммам можно говорить о том, что игры чаще выпускались после 2000 года, а критики чаще всего ставили оценки 65-70.
games.isna().sum()
Name 2 Platform 0 Year_of_Release 269 Genre 2 NA_sales 0 EU_sales 0 JP_sales 0 Other_sales 0 Critic_Score 8578 User_Score 6701 Rating 6766 dtype: int64
def pass_value_barh(data):
try:
(
(data.isna().mean()*100)
.to_frame()
.rename(columns = {0: 'space'})
.query('space > 0')
.sort_values(by='space', ascending=True)
.plot(kind='barh', figsize=(8, 6), rot=.5, legend=False, fontsize=12)
.set_title('Пропуски в данных, %', fontsize=16, color='SteelBlue')
)
except:
print('Пропусков нет')
pass_value_barh(games)
В датасете имеется довольно большое количество пропусков. Рассмотрим их ниже.
В данной части был прочитан файл с данными и просмотрены основные сведения о датесете. Далее необходимо разобраться с пропущенными значениями, дубликатами, а также подсчитать суммарные продажи.
Приведем названия колонок к нижнему регистру
games.columns = [col.lower().replace(' ', '_') for col in games.columns]
Рассмотрим типы данных в колонках
games.dtypes
name object platform object year_of_release float64 genre object na_sales float64 eu_sales float64 jp_sales float64 other_sales float64 critic_score float64 user_score object rating object dtype: object
Можно поменять типы данных в колонках:
year с float на int (год выпуска не может быть дробным)critic_score с float на int (оценка ставится по 100-больной шкале)user_score с object на float (оценка ставится по 10-больной шкале (включая дробные оценки), однако есть игры, оценка которых еще не проставлена. Такое поле заполнено значением tbd - будет определено. Следовательно можно произвести замену tbd на NaN)games.year_of_release = games.year_of_release.astype('Int64')
games.critic_score = games.critic_score.astype('Int64')
Значение tbd в колонке user_score можно рассмотреть подробнее:
games.query('user_score == "tbd"').groupby('year_of_release')['name'].count()
year_of_release 1997 1 1999 8 2000 43 2001 82 2002 192 2003 95 2004 107 2005 121 2006 124 2007 192 2008 326 2009 405 2010 331 2011 217 2012 24 2013 15 2014 21 2015 38 2016 34 Name: name, dtype: int64
Значение tbd в колонке user_score сконцентрированы с 2004 по 2011 года. Можно сделать следующие предположения:
Думаю, что лучше всего будет заменить tbd на NaN, далее просто поменять тип данных в колонке.
games.user_score = games.user_score.replace('tbd', np.nan).astype('float64')
games.isna().sum()
name 2 platform 0 year_of_release 269 genre 2 na_sales 0 eu_sales 0 jp_sales 0 other_sales 0 critic_score 8578 user_score 9125 rating 6766 dtype: int64
Имеются пропуски в колонках:
name - название игрыyear_of_release - год выпуска игрыgenre - жанр игрыcritic_score - оценка критиковuser_score - оценка пользователейРассмотрим пропуски в колонке name:
games[games['name'].isnull()]
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 659 | NaN | GEN | 1993 | NaN | 1.78 | 0.53 | 0.00 | 0.08 | <NA> | NaN | NaN |
| 14244 | NaN | GEN | 1993 | NaN | 0.00 | 0.00 | 0.03 | 0.00 | <NA> | NaN | NaN |
Строки с пропусками с колонке name можно удалить. Их мало, следовательно, они ни на что не повлияют
games = games[games['name'].notna()]
Рассмотрим пропуски в колонке year_of_release:
Сначала стоит посмотреть, имеются ли в датасете мультиплатформенные игры:
games.pivot_table(index='name', values='platform', aggfunc='count').reset_index().query('platform > 1')
| name | platform | |
|---|---|---|
| 2 | Frozen: Olaf's Quest | 2 |
| 17 | 007: Quantum of Solace | 6 |
| 18 | 007: The World is not Enough | 2 |
| 33 | 11eyes: CrossOver | 2 |
| 39 | 18 Wheeler: American Pro Trucker | 2 |
| ... | ... | ... |
| 11544 | iCarly | 2 |
| 11545 | iCarly 2: iJoin The Click! | 2 |
| 11549 | nail'd | 2 |
| 11550 | pro evolution soccer 2011 | 6 |
| 11556 | uDraw Studio: Instant Artist | 2 |
2805 rows × 2 columns
Такие игры имеются (2805 игр). Год релиза на другие платформы чаще всего несильно отличается/не отличается совсем от года релиза на основную платформу (исключения есть для игр, которые переиздаются на консоли следующего поколения). Также и оценки чаще всего несильно отличаются у мультиплатформенных игр. Однако лучше не рисковать и не трогать пропуски (и год релиза, и оценки могут сильно отличаться от платформы к платформе). Строки с пропусками в колонке год издания можно удалить. Строки с пропусками в оценках лучше оставить.
games = games[games['year_of_release'].notna()]
Рейтинг игры также может отличаться от платформы к платформе. Например, в игре Need for Speed: Most Wanted:
games.query('name == "Need for Speed: Most Wanted"')
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 253 | Need for Speed: Most Wanted | PS2 | 2005 | Racing | 2.03 | 1.79 | 0.08 | 0.47 | 82 | 9.1 | T |
| 523 | Need for Speed: Most Wanted | PS3 | 2012 | Racing | 0.71 | 1.46 | 0.06 | 0.58 | <NA> | NaN | NaN |
| 1190 | Need for Speed: Most Wanted | X360 | 2012 | Racing | 0.62 | 0.78 | 0.01 | 0.15 | 83 | 8.5 | T |
| 1591 | Need for Speed: Most Wanted | X360 | 2005 | Racing | 1.00 | 0.13 | 0.02 | 0.10 | 83 | 8.5 | T |
| 1998 | Need for Speed: Most Wanted | XB | 2005 | Racing | 0.53 | 0.46 | 0.00 | 0.05 | 83 | 8.8 | T |
| 2048 | Need for Speed: Most Wanted | PSV | 2012 | Racing | 0.33 | 0.45 | 0.01 | 0.22 | <NA> | NaN | NaN |
| 3581 | Need for Speed: Most Wanted | GC | 2005 | Racing | 0.43 | 0.11 | 0.00 | 0.02 | 80 | 9.1 | T |
| 5972 | Need for Speed: Most Wanted | PC | 2005 | Racing | 0.02 | 0.23 | 0.00 | 0.04 | 82 | 8.5 | T |
| 6273 | Need for Speed: Most Wanted | WiiU | 2013 | Racing | 0.13 | 0.12 | 0.00 | 0.02 | <NA> | NaN | NaN |
| 6410 | Need for Speed: Most Wanted | DS | 2005 | Racing | 0.24 | 0.01 | 0.00 | 0.02 | 45 | 6.1 | E |
| 6473 | Need for Speed: Most Wanted | GBA | 2005 | Racing | 0.19 | 0.07 | 0.00 | 0.00 | <NA> | 8.3 | E |
| 11715 | Need for Speed: Most Wanted | PC | 2012 | Racing | 0.00 | 0.06 | 0.00 | 0.02 | 82 | 8.5 | T |
Пропуски в колонке rating возникают из-за того, что ассоциация ESRB (Entertainment Software Rating Board) не выставила рейтинг игре. Это могло произойти по нескольким причинам:
Также все имеющиеся пропуски могли возникнуть как по причине ошибки при выгрузке данных, так и по причине отсутствия этих данных в источниках.
games.isna().sum()
name 0 platform 0 year_of_release 0 genre 0 na_sales 0 eu_sales 0 jp_sales 0 other_sales 0 critic_score 8461 user_score 8981 rating 6676 dtype: int64
Для работы в неявными дубликатами лучше рассматривать связку Название - Платформа - Год издания, чтоб исключить переиздания из дубликатов.
games.duplicated(subset=['name', 'platform', 'year_of_release']).sum()
1
В датасете есть один дубликат:
games[games.duplicated(subset=['name', 'platform', 'year_of_release'], keep=False)]
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 604 | Madden NFL 13 | PS3 | 2012 | Sports | 2.11 | 0.22 | 0.0 | 0.23 | 83 | 5.5 | E |
| 16230 | Madden NFL 13 | PS3 | 2012 | Sports | 0.00 | 0.01 | 0.0 | 0.00 | 83 | 5.5 | E |
Просуммируем продажи между собой:
games[['na_sales',
'eu_sales',
'jp_sales',
'other_sales']] = (games
.groupby(['name', 'platform', 'year_of_release'])['na_sales',
'eu_sales',
'jp_sales',
'other_sales']
.transform('sum'))
Проверка суммы:
games[games.duplicated(subset=['name', 'platform', 'year_of_release'], keep=False)]
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 604 | Madden NFL 13 | PS3 | 2012 | Sports | 2.11 | 0.23 | 0.0 | 0.23 | 83 | 5.5 | E |
| 16230 | Madden NFL 13 | PS3 | 2012 | Sports | 2.11 | 0.23 | 0.0 | 0.23 | 83 | 5.5 | E |
Проверка количества записей до удаления:
games.shape[0]
16444
Удаляем дубликаты:
games = games.drop_duplicates(subset=['name', 'platform', 'year_of_release'])
Проверка количества записей после удаления:
games.shape[0]
16443
games.duplicated(subset=['name', 'platform', 'year_of_release']).sum()
0
Рассмотрим подробнее колонку rating:
games.rating.value_counts(dropna=False)
NaN 6676 E 3920 T 2905 M 1536 E10+ 1393 EC 8 K-A 3 AO 1 RP 1 Name: rating, dtype: int64
Рейтинги означают следующее:
NaN)games.rating = games.rating.replace({'K-A': 'E', 'RP': None})
Посчитаем суммарные продажи по всем регионам:
games.insert(loc=games.columns.get_loc('critic_score'),
column='total_sales', value=round(games.loc[:, 'na_sales':'other_sales'].sum(axis=1), 3))
games.head()
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | total_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Wii Sports | Wii | 2006 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 82.54 | 76 | 8.0 | E |
| 1 | Super Mario Bros. | NES | 1985 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | 40.24 | <NA> | NaN | NaN |
| 2 | Mario Kart Wii | Wii | 2008 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 35.52 | 82 | 8.3 | E |
| 3 | Wii Sports Resort | Wii | 2009 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 32.77 | 80 | 8.0 | E |
| 4 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | 31.38 | <NA> | NaN | NaN |
В данном разделе было выполнено следующее:
Рассмотрим подробнее, сколько игр выпускалось в разные года:
games.year_of_release.hist(bins=36)
plt.title("Количество выпущенных игр по годам \n", fontsize=16)
plt.xlabel('Год', fontsize=12)
plt.ylabel('Количество игр', fontsize=12)
plt.show()
По гистограмме можно заметить, что в целом наблюдается тенденция на увеличение числа выпущенных игр в год (возможно в выгрузку попало не так много данных с 2010 по 2014 года). Нам не так сильно важны данные до 2005 года. Так как запросы аудитории меняются (число игроков увеличивается, поколения сменяют друг друга), то возможно нам стоит рассматривать данные начиная с 2008, 2009 или 2010 года.
Рассмотрим, как менялись продажи по платформам:
Найдем топ-10 платформ, лидирующих по продажам за всё время
# находим топ-10 популярных платформ
platform_total_pivot = (games.pivot_table(index='platform', values='total_sales', aggfunc='sum')
.reset_index().sort_values('total_sales', ascending=False).set_index('platform').head(10))
platform_total_pivot
| total_sales | |
|---|---|
| platform | |
| PS2 | 1233.56 |
| X360 | 961.24 |
| PS3 | 931.34 |
| Wii | 891.18 |
| DS | 802.78 |
| PS | 727.58 |
| PS4 | 314.14 |
| GBA | 312.88 |
| PSP | 289.53 |
| 3DS | 257.81 |
Первые 3 позиции занимают:
platform_pivot = games.pivot_table(index='platform',
columns='year_of_release',
values='total_sales',
aggfunc='sum').reset_index().rename_axis(None, axis=1).set_index('platform')
platform_pivot = platform_pivot[platform_pivot.index.isin(platform_total_pivot.index)].T.loc[1994:,:]
# в 1994 на платформах с самыми высокими продажами появляются первые релизы. Данные до 1994 года нам не нужны
fig = px.imshow(platform_pivot.T, labels={'y': 'Платформа',
'x': 'Год',
'color': 'Продажи, млн копий'},
title="Распределение продаж на разных платформах по годам")
fig.show()
По графикам можно говорить о том, что средний "срок жизни" платформы составляет от 7 до 10 лет
Лучше взять данные с 2013 года для проведения дальнейшего анализа.
games_2013 = games.copy(deep=True).query('year_of_release >= 2013')
Изучим продажи на разных платформах:
platform_2013_pivot = (games_2013
.pivot_table(index='platform', values='total_sales', aggfunc='sum')
.reset_index()
.sort_values('total_sales',ascending=False)
.set_index('platform'))
platform_2013_pivot = games_2013.pivot_table(index='platform',
columns='year_of_release',
values='total_sales',
aggfunc='sum').reset_index().rename_axis(None, axis=1)
platform_2013_pivot
| platform | 2013 | 2014 | 2015 | 2016 | |
|---|---|---|---|---|---|
| 0 | 3DS | 56.57 | 43.76 | 27.78 | 15.14 |
| 1 | DS | 1.54 | NaN | NaN | NaN |
| 2 | PC | 12.38 | 13.28 | 8.52 | 5.25 |
| 3 | PS3 | 113.25 | 47.76 | 16.82 | 3.60 |
| 4 | PS4 | 25.99 | 100.00 | 118.90 | 69.25 |
| 5 | PSP | 3.14 | 0.24 | 0.12 | NaN |
| 6 | PSV | 10.59 | 11.90 | 6.25 | 4.25 |
| 7 | Wii | 8.59 | 3.75 | 1.14 | 0.18 |
| 8 | WiiU | 21.65 | 22.03 | 16.35 | 4.60 |
| 9 | X360 | 88.58 | 34.74 | 11.96 | 1.52 |
| 10 | XOne | 18.96 | 54.07 | 60.14 | 26.15 |
Можно исключить платформы, у которых нет данных по продажам за 2015 и 2016 года, т.к. эти платформы уже устарели. (для исследования тенденций в игровых жанрах эти платформы лучше оставить)
platform_2013_pivot = (platform_2013_pivot[~(platform_2013_pivot[2015].isna() & platform_2013_pivot[2016].isna())]
.set_index('platform'))
fig = px.imshow(platform_2013_pivot, labels={'y': 'Платформа',
'x': 'Год',
'color': 'Продажи, млн копий'},
title="Распределение продаж на разных платформах по годам", aspect='auto')
fig.update_xaxes(type='category')
fig.layout.width = 600
fig.show()
Потенциально прибыльными платформами являются PlayStation 4 и XBox One, однако стоит делать ставку именно на PlayStation 4.
fig = px.box(games_2013,
x="platform", y="total_sales", color='platform', custom_data=['platform', 'total_sales', 'name'],
labels={'platform': 'Платформа',
'total_sales': 'Продажи, млн копий',
'name': 'Название'},
title='Разброс продаж на актуальных платформах')
fig.update_traces(
hovertemplate="<br>".join([
"Платформа: %{customdata[0]}",
"Название: %{customdata[2]}",
"Продажи, млн копий: %{customdata[1]}",
])
)
fig.update_xaxes(type='category')
fig.update_yaxes(range=[0, 1])
fig.show()
У большинства игр (вне зависимости от платформы) продажи не превышают ~ 0.8 млн копий. Медиана продаж не превышает ~0.27 млн копий. Однако она сильно колеблется от платформы к платформе
Самые большие продажи у игры PlayStation 3 и XBox 360. Но срок жизни этих платформ подходит к концу, следовательно, лучше смотреть платформы, которые следуют за ними. Это PlayStation 4, Nintendo 3DS и XBox One
Посмотрим, как влияют на продажи внутри одной популярной платформы отзывы пользователей и критиков. Построим диаграмму рассеяния и посчитаем корреляцию между отзывами и продажами.
fig = px.scatter(games_2013, x="user_score", y="total_sales", color="platform",
labels={'user_score': 'Оценка пользователей',
'total_sales': 'Продажи, млн копий',
'platform': 'Платформа'},
title="Зависимость продаж от оценки пользователей")
fig.show()
(games_2013
.groupby('platform')[['user_score', 'total_sales']]
.corr().reset_index().query('user_score < 1')
.drop({'level_1', 'total_sales'}, axis=1).sort_values('user_score', ascending=False))
| platform | user_score | |
|---|---|---|
| 15 | Wii | 0.682942 |
| 17 | WiiU | 0.419330 |
| 1 | 3DS | 0.241504 |
| 7 | PS3 | 0.002394 |
| 13 | PSV | 0.000942 |
| 19 | X360 | -0.011742 |
| 9 | PS4 | -0.031957 |
| 21 | XOne | -0.068925 |
| 5 | PC | -0.093842 |
| 11 | PSP | -1.000000 |
games_2013.user_score.corr(games_2013.total_sales)
-0.002607813354598267
Оценки пользователей корреляции с продажами не имеют
fig = px.scatter(games_2013.query('critic_score.notna()'), x="critic_score", y="total_sales", color="platform",
labels={'critic_score': 'Оценка критиков',
'total_sales': 'Продажи, млн копий',
'platform': 'Платформа'},
title="Зависимость продаж от оценки критиков")
fig.show()
(games_2013
.groupby('platform')[['critic_score', 'total_sales']]
.corr().reset_index().query('critic_score < 1')
.drop({'level_1', 'total_sales'}, axis=1).sort_values('critic_score', ascending=False))
| platform | critic_score | |
|---|---|---|
| 21 | XOne | 0.416998 |
| 9 | PS4 | 0.406568 |
| 17 | WiiU | 0.376415 |
| 1 | 3DS | 0.357057 |
| 19 | X360 | 0.350345 |
| 7 | PS3 | 0.334285 |
| 13 | PSV | 0.254742 |
| 5 | PC | 0.196030 |
games_2013.critic_score.astype('float64').corr(games_2013.total_sales)
0.3136995151027369
Оценки критиков демонстрируют прямую, слабую корреляцию с "цифрами" продаж (сильнее, чем оценки пользователей)
Посмотрим на общее распределение игр по жанрам
genre_2013_pivot = (games_2013.pivot_table(index='genre', values='total_sales', aggfunc=['count', 'sum', 'median'])
.reset_index())
genre_2013_pivot.columns = ['genre', 'count', 'sum', 'median']
genre_2013_pivot['sum'] = genre_2013_pivot['sum'].round(3)
fig = px.bar(genre_2013_pivot, x='genre', y='count',
hover_data=['sum'], color='sum',
labels={'genre': 'Жанр',
'count': 'Количество игр',
'sum': 'Суммарные продажи'},
title="Распредение количества игр по жанрам")
fig.update_layout(xaxis={'categoryorder': 'total descending'})
fig.show()
Рассмотрим медианные значения продаж по жанрам.
fig = px.bar(genre_2013_pivot, x='genre', y='median',
hover_data=['sum'], color='sum',
labels={'genre': 'Жанр',
'count': 'Медианное значение продаж',
'sum': 'Суммарные продажи'},
title="Распредение медианного количества продаж по жанрам")
fig.update_layout(xaxis={'categoryorder': 'total descending'})
fig.show()
Стоит чуть подробнее рассмотреть жанр Action, т.к. он заметно просел.
games_2013.query('genre == "Action"').sort_values('total_sales', ascending=False).head(10)
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | total_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 16 | Grand Theft Auto V | PS3 | 2013 | Action | 7.02 | 9.09 | 0.98 | 3.96 | 21.05 | 97 | 8.2 | M |
| 23 | Grand Theft Auto V | X360 | 2013 | Action | 9.66 | 5.14 | 0.06 | 1.41 | 16.27 | 97 | 8.1 | M |
| 42 | Grand Theft Auto V | PS4 | 2014 | Action | 3.96 | 6.31 | 0.38 | 1.97 | 12.62 | 97 | 8.3 | M |
| 149 | The Last of Us | PS3 | 2013 | Action | 2.41 | 2.18 | 0.28 | 0.99 | 5.86 | 95 | 9.1 | M |
| 165 | Grand Theft Auto V | XOne | 2014 | Action | 2.81 | 2.19 | 0.00 | 0.47 | 5.47 | 97 | 7.9 | M |
| 225 | The Last of Us | PS4 | 2014 | Action | 1.88 | 2.00 | 0.07 | 0.77 | 4.72 | <NA> | NaN | NaN |
| 231 | Uncharted: The Nathan Drake Collection | PS4 | 2015 | Action | 2.07 | 1.71 | 0.08 | 0.76 | 4.62 | 86 | 8.1 | T |
| 235 | Luigi's Mansion: Dark Moon | 3DS | 2013 | Action | 1.80 | 1.39 | 1.11 | 0.29 | 4.59 | 86 | 8.4 | E |
| 295 | Watch Dogs | PS4 | 2014 | Action | 1.40 | 1.90 | 0.11 | 0.64 | 4.05 | 80 | 6.3 | M |
| 304 | Assassin's Creed: Unity | PS4 | 2014 | Action | 1.19 | 2.07 | 0.08 | 0.62 | 3.96 | 70 | 4.9 | M |
games_2013.query('name == "Grand Theft Auto V"').sort_values('total_sales', ascending=False)
| name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | total_sales | critic_score | user_score | rating | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 16 | Grand Theft Auto V | PS3 | 2013 | Action | 7.02 | 9.09 | 0.98 | 3.96 | 21.05 | 97 | 8.2 | M |
| 23 | Grand Theft Auto V | X360 | 2013 | Action | 9.66 | 5.14 | 0.06 | 1.41 | 16.27 | 97 | 8.1 | M |
| 42 | Grand Theft Auto V | PS4 | 2014 | Action | 3.96 | 6.31 | 0.38 | 1.97 | 12.62 | 97 | 8.3 | M |
| 165 | Grand Theft Auto V | XOne | 2014 | Action | 2.81 | 2.19 | 0.00 | 0.47 | 5.47 | 97 | 7.9 | M |
| 1730 | Grand Theft Auto V | PC | 2015 | Action | 0.39 | 0.69 | 0.00 | 0.09 | 1.17 | 96 | 7.9 | M |
В топе есть заметный лидер - Grand Theft Auto V. Эта игра в какой-то степени помогла выбраться вперед жанру Action. Это обусловлено несколькими причинами:
Рейтинг игр всё-таки лучше составить не по полному значению продаж, а по медианному, т.к. так можно найти жарны, приносящие стабильный доход.
Топ-3 жанра по количеству игр:
Тор-3 жанра по продажам:
Жанр Action сильно выделяется как по количеству игр, так и по продажам.
Если рассматривать самые "отстающие" жанры:
Platform.Adventure (довольно сильно отличаются от средних продаж)После исследовательского анализа данных можно сделать следующие выводы:
Был определен актуальный период, за который стоит анализировать данные, готовясь к рекламной кампании в следующем (2017) году. Это период с 2013 по 2016 год. Определено, что:
Рассмотрим популярность платформ в каждом из регионов:
region_pivot = (games_2013
.pivot_table(index='platform', values=['na_sales', 'eu_sales', 'jp_sales'], aggfunc='sum')
.reset_index())
region_pivot.columns = ['platform', 'Европа', 'Япония', 'Северная Америка']
fig = px.bar(region_pivot, x='platform', y=['Европа', 'Япония', 'Северная Америка'], barmode='group',
labels={'platform': 'Платформа',
'value': 'Продажи, млн копий',
'variable': 'Регион'},
title="Популярность платформ по регионам")
fig.update_layout(xaxis={'categoryorder': 'total descending'})
fig.show()
В период с 2013 по 2016 год самыми популярными платформами:
Северной Америки являются:Европы:Японии:В Японии стараются поддерживать "своего" производителя, поэтому в топе платформ находятся "приставки" из Японии.
В Америке ситуация почти аналогичная, там поддерживают XBox, но есть и PlayStation (что может быть обусловлено относительно провальным стартом XBox One)
Европа взяла лучшие и популярные консоли из двух вышеуказанных регионов.
genre_pivot = (games_2013
.pivot_table(index='genre', values=['na_sales', 'eu_sales', 'jp_sales'], aggfunc='sum')
.reset_index())
genre_pivot.columns = ['genre', 'Европа', 'Япония', 'Северная Америка']
fig = px.bar(genre_pivot, x='genre', y=['Европа', 'Япония', 'Северная Америка'], barmode='group',
labels={'genre': 'Жанр',
'value': 'Продажи, млн копий',
'variable': 'Регион'},
title="Популярность жанров по регионам")
fig.update_layout(xaxis={'categoryorder': 'total descending'})
fig.show()
В период с 2009 по 2016 год самыми популярными жанрами:
для Северной Америки являются:
Action
Shooter
Sports
Role-Playing (RPG)
Misc
для Европы:
Action
Shooter
Sports
Role-Playing (RPG)
Racing
для Японии:
Role-Plying (RPG)
Action
Misc
Fighting
Shooter
В Японии популярен жанр RPG. Но у японцев есть свой "поджанр" - JRPG. Он сильно отличается от западных RPG. Также в Японии популярны местные консоли, для которых JRPG игры и разрабатываются (в основном).
В Америке и Европе вкусы достаточно схожи. Action и Shooter - два жанра, в которых реакция и навыки решают всё, что позволяет ввести некую соревновательную составляющую (киберспорт и спидраны).
games_2013['rating'].value_counts(dropna=False)
NaN 977 M 369 T 333 E 302 E10+ 252 Name: rating, dtype: int64
Присутствует очень много пропусков в рейтинге. Заполним пропуски значением not_given:
games_2013['rating'] = games_2013['rating'].fillna('not_given')
genre_pivot = (games_2013
.pivot_table(index='rating', values=['na_sales', 'eu_sales', 'jp_sales'], aggfunc='sum')
.reset_index())
genre_pivot.columns = ['rating', 'Европа', 'Япония', 'Северная Америка']
fig = px.bar(genre_pivot, x='rating', y=['Европа', 'Япония', 'Северная Америка'], barmode='group',
labels={'rating': 'Возрастной рейтинг',
'value': 'Продажи, млн копий',
'variable': 'Регион'},
title="Продажи игр разного возрастного рейтинга по регионам")
fig.update_layout(xaxis={'categoryorder': 'total descending'})
fig.show()
По диаграмме можно судить о том, что продажи игр в регионах не зависят от возрастного рейтинга игры.
В Северной Америке и Европе по продажам лидируют игры с рейтингом "Для взрослых" (шутеры, экшен вписываются в этот рейтинг).
В Японии же популярнее всего оказались игры с рейтингом, который не представлен в датасете. В Японии существует своя органициция по оценке игр - CERO. К тому же Японский рынок в большинстве своем очень "закрытый". Поэтому организиции ESRB (которая работает на Американский и Канадский рынки), нет смысла оценивать каждую игру, которая остается на Японском рынке (без выхода в другие регионы)
Игрок из Северной Америки:
консоли (XBox и PlayStation)Action и ShooterM (Для взрослых)Игрок из Европы:
консоли (PlayStation и XBox)Action и ShooterM (Для взрослых)Игрок из Японии:
консоли (Nintendo и PlayStation)RPG и ActionПроверка гипотезы: Средние пользовательские рейтинги платформ Xbox One и PC одинаковые
H_0: Пользовательская оценка (user_score) платформы Xbox One = Пользовательская оценка (`user_score`) платформы PC`
H_1: Пользовательская оценка (user_score) платформы Xbox One ≠ Пользовательская оценка (`user_score`) платформы PC`
alpha = 0.05
results = st.ttest_ind(games_2013.dropna().query('platform == "XOne"')['user_score'],
games_2013.dropna().query('platform == "PC"')['user_score'], equal_var=False)
alpha = .05
print(results.pvalue)
if results.pvalue < alpha:
print('Отвергаем нулевую гипотезу')
else:
print('Не получилось отвергнуть нулевую гипотезу')
0.1788264826340131 Не получилось отвергнуть нулевую гипотезу
Вероятность получить такую же оценку составляет ~ 20%. Вероятность достаточно большая, чтобы делать вывод о значительном различиями между средними оценками.
Средние пользовательские рейтинги платформ Xbox One и PC ~ одинаковые
Проверка гипотезы: Средние пользовательские рейтинги жанров Action и Sports разные
H_0: Пользовательская оценка (user_score) жанра Action = Пользовательская оценка (`user_score`) жанра Sport`
H_1: Пользовательская оценка (user_score) жанра Action ≠ Пользовательская оценка (`user_score`) жанра Sport`
alpha = 0.05
results = st.ttest_ind(games_2013.dropna().query('genre == "Action"')['user_score'],
games_2013.dropna().query('genre == "Sports"')['user_score'], equal_var=False)
alpha = .05
print(results.pvalue)
if results.pvalue < alpha:
print('Отвергаем нулевую гипотезу')
else:
print('Не получилось отвергнуть нулевую гипотезу')
1.0496920005008586e-13 Отвергаем нулевую гипотезу
Вероятность получить такую же оценку составляет ~ 0%. Вероятность достаточно мала, следовательно средние пользовательские оценки не равны
Средние пользовательские рейтинги жанров Action и Sports разные
В проекте была проделана работа по предобработке данных.
Были обнаружены пропуски в колонках с оценками и рейтингами. Возможно датасет стоило вернуть на доработку.
Были проанализированы различные игровые платформы и жанры игр. Обнаружено, что:
Был составлен портрет пользователя каждого из представленных регионов.
Игрок из Северной Америки:
играет на консоли (XBox и PlayStation)
любит игры жанра Action и Shooter
предпочитает игры с возрастным рейтингом M (Для взрослых)
Игрок из Европы:
играет на консоли (PlayStation и XBox)
любит игры жанра Action и Shooter
предпочитает игры с возрастным рейтингом M (Для взрослых)
Игрок из Японии:
играет на консоли (Nintendo и PlayStation)
любит игры жанра RPG и Action
предпочитает игры со своего рынка, которые не были оценены ESRB
Также обнаружено, что:
Самыми перспективными платформами оказались PlayStation 4 и XBox One. Именно на них стоит делать ставку во время рекламной кампании на следующий год. Большее внимание стоит уледить платформе PlayStation 4
По жанрам стоит обратить внимание на Shooter, Sports и Platform (жанры для всех регионов).
Если же делать отдельные рекламные кампании для отдельных регионов, то лучше обращаться к портрету пользователя для выявления трендов региона.